package com.visikard.utility;

import java.io.ByteArrayOutputStream;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;

public final class BitmapUtils {
	public static final int CORNER_PERCENT = 8;
	
	/*
	 * flag use for round image conrner
	 */
	public static final int ROUND_NONE = 0;
	public static final int ROUND_ALL = 1;
	public static final int ROUND_TOP = 2;
	public static final int ROUND_BOTTOM = 3;
	public static final int CIRCLE = 4;
	
//round corner----------------------------------------------------------------------------//		
		
	/**
	 * round bitmap by roundType
	 * @param bitmap
	 * @param roundType
	 * @return
	 */
	public static Bitmap getRoundedCornerBitmap( Bitmap bitmap, int roundType , int roundPercent) {
		Bitmap output = bitmap;
		
		switch (roundType) {
		case ROUND_ALL:
			output = getRoundedCornerBitmap(bitmap, roundPercent);
			break;
		case ROUND_TOP:
			output = getRoundedTopCornerBitmap(bitmap);
			break;
		case ROUND_BOTTOM:
			output = getRoundedBottomCornerBitmap(bitmap);
			break;
		case CIRCLE:
			output = getCircleBitmap(bitmap);
			break;
		}
		
		return output;
	}
	
	/**
	 * round bitmap's 4 corner
	 * @param bitmap
	 * @return
	 */
	private static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int roundPercent) {
		Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
				bitmap.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(output);
		final Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setFilterBitmap(true);
		paint.setColor(0xffffffff);

		final Rect rectFullSize = new Rect(0, 0, bitmap.getWidth(),
				bitmap.getHeight());
		final RectF rectFFullSize = new RectF(rectFullSize);
		final float roundPx = bitmap.getWidth() * roundPercent / 100;
		
		canvas.drawRoundRect(rectFFullSize, roundPx, roundPx, paint);
		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(bitmap, rectFullSize, rectFullSize, paint);
		
		return output;
	}
	/**
	 * round bitmap's 4 corner
	 * @param bitmap using default values of corner round percent
	 * @return
	 */
	private static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
		Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
				bitmap.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(output);
		final Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setFilterBitmap(true);
		paint.setColor(0xffffffff);

		final Rect rectFullSize = new Rect(0, 0, bitmap.getWidth(),
				bitmap.getHeight());
		final RectF rectFFullSize = new RectF(rectFullSize);
		final float roundPx = bitmap.getWidth() * CORNER_PERCENT / 100;
		
		canvas.drawRoundRect(rectFFullSize, roundPx, roundPx, paint);
		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(bitmap, rectFullSize, rectFullSize, paint);
		
		return output;
	}		
	
	/**
	 * round bitmap's 2 top corner
	 * @param bitmap
	 * @return
	 */
	private static Bitmap getRoundedTopCornerBitmap(Bitmap bitmap) {
		Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
				bitmap.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(output);

		final Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setFilterBitmap(true);
		paint.setColor(0xffffffff);

		final Rect rectFullSize = new Rect(0, 0, bitmap.getWidth(),
				bitmap.getHeight());
		final float roundPx = bitmap.getWidth() * CORNER_PERCENT / 100;
		final Rect rectFullSizeTop = new Rect(0, 0, bitmap.getWidth(),
				bitmap.getHeight() + (int) roundPx);
		final RectF rectFFullSizeTop = new RectF(rectFullSizeTop);

		canvas.drawRoundRect(rectFFullSizeTop, roundPx, roundPx, paint);
		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(bitmap, rectFullSize, rectFullSize, paint);

		return output;
	}	
	
	/**
	 * round bitmap's 2 bottom corner
	 * @param bitmap
	 * @return
	 */
	private static Bitmap getRoundedBottomCornerBitmap(Bitmap bitmap) {
		Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
				bitmap.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(output);

		final Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setFilterBitmap(true);
		paint.setColor(0xffffffff);

		final Rect rectFullSize = new Rect(0, 0, bitmap.getWidth(),
				bitmap.getHeight());
		final float roundPx = bitmap.getWidth() * CORNER_PERCENT / 100;
		final Rect rectFullSizeTop = new Rect(0, (int) -roundPx, bitmap.getWidth(),
				bitmap.getHeight());
		final RectF rectFFullSizeTop = new RectF(rectFullSizeTop);

		canvas.drawRoundRect(rectFFullSizeTop, roundPx, roundPx, paint);
		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(bitmap, rectFullSize, rectFullSize, paint);

		return output;
	}

//shadow----------------------------------------------------------------------------//	
	
	public static Bitmap addShadow( Bitmap bitmap, int shadowWidtbPercent, int shadowRestId, Context context ) {
		return addShadow(bitmap, shadowWidtbPercent,BitmapFactory.decodeResource(context.getResources(), shadowRestId));
	}
	/**
	 * add shadow to a bitmap
	 * @param bitmap bitmap to add shadow
	 * @param shadowWidtbPercent percent of input bitmap width to use for shadow 
	 * @param shadowBitmap bitmap to use as shadow
	 * @return
	 */
	public static Bitmap addShadow( Bitmap bitmap, int shadowWidtbPercent, Bitmap shadowBitmap ) {

		Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
				bitmap.getHeight(), Config.ARGB_8888);
		Canvas canvas = new Canvas(output);

		final Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setFilterBitmap(true);
		paint.setColor(0xffffffff);

		Rect bitmapRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
		Rect shadowRect = new Rect(0, 0, shadowBitmap.getWidth(), shadowBitmap.getHeight());		
		int shadowWidth = bitmap.getWidth() * shadowWidtbPercent / 100;		
		Rect bitmapShadowRect = new Rect(shadowWidth, shadowWidth * bitmap.getHeight() / bitmap.getWidth(),
				bitmap.getWidth() - shadowWidth, bitmap.getHeight() - shadowWidth * bitmap.getHeight() / bitmap.getWidth());
				
		canvas.drawBitmap(shadowBitmap, shadowRect, bitmapRect, paint);
		canvas.drawBitmap(bitmap, bitmapRect, bitmapShadowRect, paint);			

		return output;
	}
	
//----------------------------------------------------------------------------//		
	
	/**
	 * crop bitmap by ratio
	 * ratio is percent of width in compare with height
	 * ex: 25 - mean crop witdh to de 25% of height
	 * @param ratio
	 * @return
	 */
	public static Bitmap cropBitmapByRatio( Bitmap bitmap, int ratio ) {
		Bitmap output = null;
		
		int srcW = bitmap.getWidth();
		int srcH = bitmap.getHeight();
		int desW = srcW, desH = srcH;
		int l = 0, t = 0, r = srcW, b = srcH;		
		if( srcW * 100 < srcH * ratio ) {
			//crop height
			desH = desW * 100 / ratio;
			
			l = 0;
			r = srcW;
			t = (srcH - desH)/2;
			b = srcH - (srcH - desH)/2;
		} else {
			//crop width
			desW = desH * ratio / 100;
			
			t = 0;
			b = srcH;
			l = (srcW - desW)/2;
			r = srcW - (srcW - desW)/2;
		}
		
		output = Bitmap.createBitmap( desW, desH, Config.ARGB_8888);
		Canvas canvas = new Canvas(output);
		
		Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setFilterBitmap(true);
		paint.setColor(0xffffffff);
		
		Rect srcRect = new Rect(l, t, r, b);
		Rect desRect = new Rect(0, 0, desW, desH);
		
		canvas.drawBitmap(bitmap, srcRect, desRect, paint);
		
		return output;
	}
	
	/**
	 * crop bitmap by rect zone
	 * @param bitmap
	 * @param startX
	 * @param endX
	 * @param startY
	 * @param endY
	 * @return
	 */
	public static Bitmap cropBitmap( Bitmap bitmap, int startX, int endX, int startY, int endY ) {
		Bitmap output = Bitmap.createBitmap( endX - startX, endY - startY, Config.ARGB_8888);
		Canvas canvas = new Canvas(output);
		
		Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setFilterBitmap(true);
		paint.setColor(0xffffffff);
		
		Rect srcRect = new Rect(startX, startY, endX, endY);
		Rect desRect = new Rect(0, 0, endX - startX, endY - startY);
		
		canvas.drawBitmap(bitmap, srcRect, desRect, paint);
		
		return output;
	}
	
//----------------------------------------------------------------------------//	

	public static ByteArrayOutputStream getByteArrayOutputStream(Bitmap bitmap,
			int quality) {
		if (bitmap == null || quality < 0 || quality > 100)
			return null;
		try {
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			if (bitmap.compress(CompressFormat.JPEG, quality, bos)) {
				return bos;
			} else
				return null;
		} catch (OutOfMemoryError e) {
			e.printStackTrace();
			return null;
		} catch (IllegalStateException e) {
			e.printStackTrace();
			return null;
		}
	}
	
	public static byte[] decodeByteArrayEffectOverLay(Bitmap tmpBitmap) {
		int offset = 0;
		byte[] result = new byte[tmpBitmap.getWidth() * tmpBitmap.getHeight()
				* 3];
		for (int i = 0; i < tmpBitmap.getHeight(); i++) {
			for (int j = 0; j < tmpBitmap.getWidth(); j++) {
				int pixelColor = tmpBitmap.getPixel(j, i);
				result[offset++] = (byte) ((pixelColor >> 16) & 0xFF);
				result[offset++] = (byte) ((pixelColor >> 8) & 0xFF);
				result[offset++] = (byte) (pixelColor & 0xFF);
			}
		}
		return result;
	}
	
//----------------------------------------------------------------------------//	
	
	public static Bitmap dropCenterImage(Bitmap bmp, int newWidth) {
		int w = bmp.getWidth();
		int h = bmp.getHeight();
		if (newWidth >= w)
			return bmp;
		float scale = newWidth * 1.0f / w;
		int newHeight = (int) (h * scale);
		Bitmap result = Bitmap.createBitmap(newWidth, newHeight,
				Config.ARGB_8888);
		Canvas canvas = new Canvas(result);
		int left = (w - newWidth) / 2;
		int top = (h - newHeight) / 2;
		canvas.drawBitmap(bmp, left, top, new Paint());
		return result;
	}
	
	/**
	 * just use for buisiness kard
	 */
	public static Bitmap createBottomRoundedCornerBitmap(int width, int height) {
		Bitmap output = Bitmap.createBitmap(width,
				height, Config.ARGB_8888);
		Canvas canvas = new Canvas(output);
		final Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setFilterBitmap(true);
		paint.setColor(0xaa000000);

		final float roundPx = output.getWidth() * CORNER_PERCENT / 100;
		final Rect rectFullSize = new Rect(0, (int) -roundPx, output.getWidth(),
				output.getHeight());
		final RectF rectFFullSize = new RectF(rectFullSize);
		
		canvas.drawRoundRect(rectFFullSize, roundPx, roundPx, paint);
		return output;
	}
	
	public static Bitmap scaleCenterCrop(Paint mTextPaint, Bitmap source, int newHeight, int newWidth) {
		int sourceWidth = source.getWidth();
		int sourceHeight = source.getHeight();

		// Compute the scaling factors to fit the new height and width, respectively.
		// To cover the final image, the final scaling will be the bigger 
		// of these two.
		float xScale = (float) newWidth / sourceWidth;
		float yScale = (float) newHeight / sourceHeight;
		float scale = Math.max(xScale, yScale);

		// Now get the size of the source bitmap when scaled
		float scaledWidth = scale * sourceWidth;
		float scaledHeight = scale * sourceHeight;

		// Let's find out the upper left coordinates if the scaled bitmap
		// should be centered in the new size give by the parameters
		float left = (newWidth - scaledWidth) / 2;
		float top = (newHeight - scaledHeight) / 2;

		// The target rectangle for the new, scaled version of the source bitmap will now
		// be
		RectF targetRect = new RectF(left, top, left + scaledWidth, top + scaledHeight);

		// Finally, we create a new bitmap of the specified size and draw our new,
		// scaled bitmap onto it.
		Bitmap dest = Bitmap.createBitmap(newWidth, newHeight, source.getConfig());
		Canvas canvas = new Canvas(dest);
		canvas.drawBitmap(source, null, targetRect, mTextPaint);

		return dest;
	}
	
	public static Bitmap rotate(Bitmap bitmap, int degree) {
	    int w = bitmap.getWidth();
	    int h = bitmap.getHeight();

	    Matrix mtx = new Matrix();
	    mtx.postRotate(degree);

	    return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
	}	
	
	/**
	 * get the center circle form input bitmap
	 * @param bitmap
	 * @return
	 */
	public static Bitmap getCircleBitmap(Bitmap bitmap) {
		int sizeW = bitmap.getWidth();
		int sizeH = bitmap.getHeight();
		int radius2x = sizeW;
		if(radius2x > sizeH) {
			radius2x = sizeH;
		}
		int radius = radius2x / 2;
		
		Bitmap output;
		if(Utils.hasHoneycomb())
			output = Bitmap.createBitmap(sizeW,
					sizeH, Config.ARGB_8888);
		else
			output = Bitmap.createBitmap(sizeW,
					sizeH, Config.RGB_565);
		Canvas canvas = new Canvas(output);
		canvas.drawARGB(0, 0, 0, 0);
		final Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setFilterBitmap(true);
		paint.setColor(0xffffffff);
		
		final Rect rectFullSize = new Rect(0, 0, sizeW,sizeH);
		canvas.drawCircle(sizeW / 2, sizeH / 2, radius, paint);
		paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		canvas.drawBitmap(bitmap, rectFullSize, rectFullSize, paint);
		
		return output;
	}
}
